//=============================================
//	AND Function
//=============================================

module f_and(z,x,y,en); // and function

	input [7:0] x,y;
	input en;
	output [7:0] z;

	and a1[7:0](z,x,y,en);
	

endmodule

//=============================================
//	OR Function 
//=============================================

module f_or(z,x,y,en); //or function

	input [7:0] x,y;
	input en;
	output [7:0] z;
	wire [7:0] w;        


	or o1 [7:0] (w,x,y);
         and a1[7:0] (z,w,en);



endmodule

//=============================================
//	Adder Function
//=============================================

module HA(Cout,SUM,A,B);  // 1bit half adder
    
    input    A,B        ;
    output   SUM, Cout  ;
    
    and a1(Cout,A,B);
    xor x1(SUM,A,B);
    
endmodule

module FA(cout,sum,a,b,cin);  // 1bit full adder

	input a,b,cin;
	output cout,sum;
	wire w1,w2,w3;

	HA 	a1(w1,w2,a,b);
	HA 	a2(w3,sum,w2,cin);
	xor 	x1(cout,w3,w1);

endmodule

module FA8(cout,sum,a,b,en);

	input [7:0] a,b;
        	input en;
	output cout;
	output [7:0] sum;
	
	wire [7:0] esum,w1;
	wire ecout;

	FA a0(w1[0],esum[0],a[0],b[0],{1'b0});
	FA a1(w1[1],esum[1],a[1],b[1],w1[0]);
	FA a2(w1[2],esum[2],a[2],b[2],w1[1]);
	FA a3(w1[3],esum[3],a[3],b[3],w1[2]);
	FA a4(w1[4],esum[4],a[4],b[4],w1[3]);
	FA a5(w1[5],esum[5],a[5],b[5],w1[4]);
	FA a6(w1[6],esum[6],a[6],b[6],w1[5]);
	FA a7(ecout,esum[7],a[7],b[7],w1[6]);
	
	and b1[7:0] (sum,esum,en);
	and b2 (cout,ecout,en);
	
	
endmodule

//=============================================
//	Substrator Function
//=============================================

module sub8(cout,sum,a,b,en); //substractor

	input [7:0] a,b;
        input en;
	output cout;
	output [7:0] sum;
	
	wire [7:0] esum,w1,xb;
	wire ecout;

	xor p0[7:0] (xb,b,{8{1'b1}});
	FA a0(w1[0],esum[0],a[0],xb[0],{1'b1});
	FA a1(w1[1],esum[1],a[1],xb[1],w1[0]);
	FA a2(w1[2],esum[2],a[2],xb[2],w1[1]);
	FA a3(w1[3],esum[3],a[3],xb[3],w1[2]);
	FA a4(w1[4],esum[4],a[4],xb[4],w1[3]);
	FA a5(w1[5],esum[5],a[5],xb[5],w1[4]);
	FA a6(w1[6],esum[6],a[6],xb[6],w1[5]);
	FA a7(ecout,esum[7],a[7],xb[7],w1[6]);
	
	and b1[7:0] (sum,esum,en);
	and b2 (cout,ecout,en);
	
	
endmodule

//=============================================
//	SLT Function
//=============================================

module dec2to4(c,a,b); //2to4 decoder

	input a,b;
	output [3:0]c;
	wire na,nb;

	not n1 (nb,b);
   	not n2 (na,a);

	and a1 (c[0],na,nb);
	and a2 (c[1],na,b);
	and a3 (c[2],a,nb);
	and a4 (c[3],a,b);

endmodule


module dec_slt(sel,sum,c); //creat mux's sel value

	input [3:0] c;
	input sum	;
	output	sel	;

	wire n_sum	;
	wire [3:0] n_c	;
	wire [3:0] w_sel;

	not n0[3:0](n_c,c);
	not n1(n_sum,sum);

	and a0(w_sel[0],n_sum,n_c[3],c[2],n_c[1],n_c[0]);
	and a1(w_sel[1],n_sum,c[3],n_c[2],n_c[1],n_c[0]);
	and a2(w_sel[2],sum,n_c[3],n_c[2],n_c[1],c[0]);
	and a3(w_sel[3],sum,n_c[3],c[2],n_c[1],n_c[0]);
		
	or o1(sel,w_sel[3],w_sel[2],w_sel[1],w_sel[0]);

endmodule 

module mux(z,x,y,sel); //2to1 mux

	input sel	;
	input [7:0]	x,y	;
	output [7:0] 	z	;

	wire n_sel	;
	wire [7:0]	w1,w2;

	not n1(n_sel,sel);

	and a1[7:0](w1,x,n_sel);
	and a2[7:0](w2,y,sel);
	
	or o1[7:0](z,w1,w2);

endmodule

module slt(z,x,y,en); //slt module

	input [7:0] x,y;
	input en; 	
	
	output [7:0] z;
	

	wire [3:0]w1;
	wire w2;
	wire [7:0] sum;
	wire cout;
  	wire esel;
	wire [7:0] wx,wy;
	
	and a1[7:0](wx,x,en);
	and a2[7:0](wy,y,en);

	dec2to4	 d1(w1,wx[7],wy[7]);
        or	 o1(w2,w1[0],w1[3]);
	sub8	 s1(cout,sum,wx,wy,w2);
	dec_slt	 k0(esel,sum[7],{w1[0],w1[1],w1[2],w1[3]});
	mux	 m0(z,wx,wy,esel);


endmodule


//=============================================
//	Top module
//=============================================

module dec3to8(d,a,b,c); //3to8 decoder

	input a,b,c;
	output [7:0]d;
	wire na,nb,nc;

	not n1 (nb,b);
   	not n2 (na,a);
   	not n3 (nc,c);

	and a0(d[0],na,nb,nc);
	and a1(d[1],na,nb,c);
	and a2(d[2],na,b,nc);
	and a3(d[3],na,b,c);
	and a4(d[4],a,nb,nc);
	and a5(d[5],a,nb,c);
	and a6(d[6],a,b,nc);
	and a7(d[7],a,b,c);
	
endmodule

module top(z,alu,x,y, zero);

	input [7:0] x,y;
	input [2:0] alu;
	
	output [7:0] z;
	output zero;

	wire [7:0] d;
	wire [7:0] z1,z2,z3,z4,z5;
	wire cout1,cout2;

	dec3to8 p0(d,alu[2],alu[1],alu[0]);
	f_and	p1(z1,x,y,d[0]);
	f_or	p2(z2,x,y,d[1]);
	ALU_AdderFraction AD(.A(x), .B(y), .Result(z3), .m2(d[2]), .m6(d[6]), .m7(d[7]));
	
	or o1[7:0] (z,z1,z2,z3);

	assign zero=~|{z};

endmodule
